/**
 * FileName: LoginServiceImpl
 * Author: TangZaoBang
 * Date: 2023/06/05 13:09
 * Description: 登录服务
 * <p>
 * History:
 * <author> TangZaoBang
 * <time> 2023/06/05 13:09
 * <version> 1.0.0
 * <desc> 版本描述
 */
package com.sd365.permission.centre.service.impl;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.util.BeanUtil;
import com.sd365.permission.centre.dao.mapper.ResourceMapper;
import com.sd365.permission.centre.dao.mapper.RoleMapper;
import com.sd365.permission.centre.dao.mapper.TenantMapper;
import com.sd365.permission.centre.dao.mapper.UserMapper;
import com.sd365.permission.centre.entity.Resource;
import com.sd365.permission.centre.entity.Role;
import com.sd365.permission.centre.entity.User;
import com.sd365.permission.centre.pojo.dto.RoleDTO;
import com.sd365.permission.centre.pojo.dto.UserDTO;
import com.sd365.permission.centre.pojo.vo.ResourceVO;
import com.sd365.permission.centre.service.LoginService;
import com.sd365.permission.centre.service.MenuService;
import com.sd365.permission.centre.service.UserOnlineService;
import com.sd365.permission.centre.service.util.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;


/**
 * 实现登录认证和用户信息获取功能
 * @ClassName LoginServiceImpl
 * @author TangZaoBang
 * @date 2023/06/15 02:00
 * @version 1.0.0
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    private static final Byte ONLINE_STATUS=3;

    /**
     * 用于操作user表验证账号密码
     */
    @Autowired
    private UserMapper userMapper;
    /**
     * 查询租户相关信息
     */
    @Autowired
    private TenantMapper tenantMapper;
    /**
     * 查询角色相关信息
     */
    @Autowired
    private RoleMapper roleMapper;
    /**
     * 查询资源相关信息针对resource表
     */
    @Autowired
    private ResourceMapper resourceMapper;
    /**
     * 主要用于构建菜单
     */
    @Autowired
    private MenuService menuService;

    /**
     * 引入做登录状态更新和登录进入插入
     */
    @Autowired
    private UserOnlineService userOnlineService;


    /**
     * 验证登录用户状态：账号(code)和租户(account)不匹配，即 "该账户不存在"，返回0
     *  账号和租户匹配，但密码错误，返回2
     *  账号和租户存在数据库且匹配，以及密码正确，则登录成功，返回1
     * @author TangZaoBang
     * @date 2023/06/10 13:29
     * @param code code
     * @param password password
     * @param account account
     * @return int 账号错误  1:登录成功  2:密码错误
     */
    @Override
    public int verification(String code, String password, String account) {
        User user = userMapper.selectNameByCodePassword(code, password);
        if (null != user) {
            // 可能存在租户输入错误的情况
            Long tenantId = tenantMapper.selectTenantIdByTenantAccount(account);
            if (tenantId == null || !tenantId.equals(user.getTenantId())) {
                return LOGIN_VERIFY_CODE_TENANT_ERR;
            } else {
                return LOGIN_VERIFY_CODE_SUCCESS;
            }
        } else {
            // 账号或者或者密码已经错误
            return LOGIN_VERIFY_CODE_CODE_OR_PASSWORD_ERR;
        }
    }
    /**
     *
     * @author TangZaoBang
     * @date 2023/06/10 13:17
     * @param code 工号
     * @param password 密码
     * @param account 租户号
     * @return com.sd365.permission.centre.pojo.vo.UserVO
     */
    @Override
    public UserVO login(@Validated @NotNull  String code, @Validated @NotNull  String password, @Validated @NotNull String account) {
        int flag = verification(code, Md5Utils.digestHex(password), account);
        if (flag == 1) {
            return BeanUtil.copy(getUserInfo(code, account), UserVO.class);

        } else if (flag == 0) {
            throw new BusinessException("401","账号和租户不匹配或不存在");
        } else {
            throw new BusinessException("401","用户名或密码错误，登录失败");
        }
    }

    @Override
    public User getUserInfo(@Validated @NotNull  String code,@Validated @NotNull  String account) {
        Long tenantId = tenantMapper.selectTenantIdByTenantAccount(account);
        return userMapper.selectUserByCodeTenantid(code, tenantId);

    }

    @Override
    public List<Role> getRolesByUserId(@Validated @NotNull Long userId) {
        return  roleMapper.selectRolesByUserId(userId);

    }

    @Override
    public List<ResourceVO> getResourceVO(@NotEmpty List<Role> roles) {
        /**
         * 根据角色取得所有的角色id加入列表
         */
        List<Long> roleIds = new ArrayList<>();
        Iterator<Role> it = roles.iterator();
        while (it.hasNext()) {
            roleIds.add(it.next().getId());
        }
        List<Resource> resources = resourceMapper.getResourceByRoleId(roleIds);
        return  menuService.buildMenu(resources);

    }

    @Override
    public Boolean updateUserOnlineStatus(@Validated @NotNull Long userId, @Validated @NotNull byte status) {

        return userMapper.updateUserOnlineStatus(userId, status) > 0;
    }


    @Override
    public UserDTO auth(@Validated @NotNull String code, @Validated @NotNull String password, @Validated @NotNull String account) {

        UserDTO userDTO = new UserDTO();
        /**
         * 插入登录记录并且更新登录状态
         */
        int result = verification(code, Md5Utils.digestHex(password), account);
        if (LoginServiceImpl.LOGIN_VERIFY_CODE_SUCCESS == result) {
            User user = getUserInfo(code, account);
            List<Role> roles = getRolesByUserId(user.getId());
            List<RoleDTO> roleDTOS = new ArrayList<>();
            for (Role role:roles){
                RoleDTO roleDTO = new RoleDTO();
                BeanUtil.copy(role,roleDTO,RoleDTO.class);
                roleDTOS.add(roleDTO);
            }
            userDTO.setId(user.getId());
            userDTO.setName(user.getName());
            userDTO.setRoleList(roleDTOS);
            userDTO.setTenantId(user.getTenantId());
            userDTO.setOrgId(user.getOrgId());
            userDTO.setCompanyId(user.getCompanyId());
            // 用户登陆判断
            if (user.getStatus().intValue() == LOGIN_VERIFY_CODE_SUCCESS && !user.getStatus().equals(ONLINE_STATUS)) {
                // 登陆成功修改status值
                updateUserOnlineStatus(user.getId(), ONLINE_STATUS);
            }
            // 保存登陆信息
            userOnlineService.saveLoginInfo(user);
        }
        else if (result == 0) {
            throw new BusinessException("401","账号和租户不匹配或不存在");
        } else {
            throw new BusinessException("401","用户名或密码错误，登录失败");
        }
        return userDTO;
    }




}
